#!/usr/bin/perl

use FindBin qw($Bin);
use lib "$Bin/../lib";  

###################################################################
# CONFIGURATION
# the path to your maude 2 binary
$maudepath = "maude.linux";
###################################################################

$tmpfile="ftLTLtmp";
$pgmfile = "$Bin/min5.maude";

my $ere_orig ;
my $res = "";

my $filename;
my $dot_input;
my $maude_input;

@predicates =();
@predicate2expr = ();
@fncts = ();
@events = ();
$flag = 0;
while (<>){
    s/\/\/.*//;
    if ($flag == 0) {
	if (/Predicate\s+(\S+)\s*\:(.*)\;/) {
	    $predicates[$#predicates+1] = $1 ;
	    $predicate2expr{$1} = "($2)";	
	} else {
	    if (/Event\s+(\S+)\s*\:(.*)\;/) {
		$fncts[$#fncts+1] = $1 ;
	    } else{
		if (/Formula\s*\:/) {
		    s/;//g;
		    s/Formula\s*\://;
		    s/\(\*\)/{*}/g;
		    s/\)s/}s/g;
                    s/\)w/}w/g;
	            s/\!|\/\\|\\\/|\-\>|\<\-\>|\+\+|\{\*\}|\[\*\]|\<\*\>|\[|\}s|\}w/ $& /g;
	            s/\s+/ /g;
	            for ($i = 0; $i <= $#fncts; $i ++){
			if (/start\($fncts[$i]\)/){
			    $events[$#events+1] = "\#start-$fncts[$i]";
			    s/start\($fncts[$i]\)/\$start\-$fncts[$i]/g;
			}
			if (/end\($fncts[$i]\)/){
			    $events[$#events+1] = "\$end-$fncts[$i]";
			    s/end\($fncts[$i]\)/\$end\-$fncts[$i]/g;
			}
			if (/(.)$fncts[$i]/){
			    $tmp = $1;
			    if (! ($tmp =~ /\-/)){
				$events[$#events+1] = "\#end-$fncts[$i]";
				s/$tmp$fncts[$i]/$tmp\$end\-$fncts[$i]/g;
			    }
			}
	            }
	            $ere_orig=$_;
	            $flag = 1;
                 }
            }
	}
     } else {
        if ((/Violation\sHandler/) || (/Validation\sHandler/)){
	    $flag = 0;
        } else { 
	    s/;//g;
	    s/\(\*\)/{*}/g;
	    s/\)s/}s/g;
            s/\)w/}w/g;
            s/\!|\/\\|\\\/|\-\>|\<\-\>|\+\+|\{\*\}|\[\*\]|\<\*\>|\[|\}s|\}w/ $& /g;
            s/\s+/ /g;
            for ($i = 0; $i <= $#fncts; $i ++){
		if (/start\($fncts[$i]\)/){
		    $events[$#events+1] = "start-$fncts[$i]";
		    s/start\($fncts[$i]\)/start\-$fncts[$i]/g;
		}
		if (/end\($fncts[$i]\)/){
		    $events[$#events+1] = "end-$fncts[$i]";
		    s/end\($fncts[$i]\)/end\-$fncts[$i]/g;
		}
		if (/(.)$fncts[$i]/){
		    $tmp = $1;
		    if (! ($tmp =~ /\-/)){
			$events[$#events+1] = "end-$fncts[$i]";
			s/$tmp$fncts[$i]/end\-$fncts[$i]/g;
		    }
		}
            }
	    $ere_orig = $ere_orig.$_; 
	}
     }
}
create_maude_input();
exec_maude();
create_output();

sub create_maude_input {
    $ere_orig =~ s/[\r\n]/ /g;
    my $ere = $ere_orig;
    $ere =~ s/empty/\$/g ;
    $ere =~ s/epsilon/\!/g ;
    $ere =~ s/([\!\$\~\+\&\*\(\)])/ $1 /g;
    $ere =~ s/\s+/ /g;

    my @alphs = split /[\!\$\~\+\&\*\(\)\s]/, $ere ;
    shift @alphs;
    my %alphs;
    my $elt;
    foreach $elt (@alphs) {
        $alphs{$elt} = 1;
    }
    my $ops = "";
    my $eset = "  eq eset = ";


    foreach $elt (keys %alphs){
	if ($elt =~ /(\w|-)+/){
	    $ops = $ops."  op $elt : -> Event .\n";
	    $eset = $eset." $elt \#";
	}
    }
    chop $eset ;
    $eset = $eset." .\n";
    $ere =~ s/\$/empty/g;
    $ere =~ s/\!/epsilon/g;

    $maude_input = "in $pgmfile\n";
    $maude_input = $maude_input.$ops.$eset."endfm\n";
    $maude_input = $maude_input."red build($ere) .\n";
    $maude_input = $maude_input."quit .\n";
}

sub exec_maude{

    open MAUDEIN, "|$maudepath > $tmpfile.mout" || die "Cannot execute $maudepath\n";
    print MAUDEIN $maude_input;
    close MAUDEIN;

    open MAUDEOUT, "<$tmpfile.mout" || die "Cannot open /tmp/dfa.out$i\n";
    my $flag = 0;
    my $line;
    while($line = <MAUDEOUT>){
        chomp($line);
        if($line =~ /^result Automata: (.*)$/){
            $res = $1;
            $flag = 1;
        }
        else {
            if($line =~ /^Bye/) {
                $flag = 0;
            }
            if($flag) {
                $res = $res.$line;
            }}
    }
    close(MAUDEOUT);
    unlink "$tmpfile.mout";
}

sub create_output{
    $res =~ /^\{(.*)\}$/;
    if ($1 =~ /(.+)/){
	$res = $1;
    } else {
	$res = "";
	print "Extended Regular Expression: Cannot deal with the logic input.\n";
	exit 1;
    }

    $state = "\$state" ;
    print "// Declaration \n int $state = 0; \n";
    for ($i = 0; $i <= $#events; $i ++){
	$item = $events[$i];
	$item =~ s/(.+)\-(.+)/$1($2)/;
	print "fnct \$$events[$i] = $item;\n";
    }
    print "// Monitoring body\n" ;
    print "switch($state) { \n ";
    my %statements;

    while($res =~ /\[\s*(\w+)\s*,\s*([\w\-]+)\s*\]\W+(\w+)(.*)/){
	if (defined($statements{$1})){
	    $statements{$1} = $statements{$1}."$2 ? $3 :";
	} else {
	    $statements{$1} = "case $1 :\n $state = "."$2 ? $3 :";
	}
        $res = $4;
    }

    foreach $k (keys %statements){
	$statements{$k} = $statements{$k}."-2 ;\n break;\n";
	for ( $ii = 0 ; $ii <= $#predicates ; $ii ++) {
	    $statements{$k} =~ s/(\W)$predicates[$ii]/$1$predicate2expr{$predicates[$ii]}/g;
	}
	for ($ii = 0; $ii <= $#events; $ii ++){
	    $statements{$k} =~ s/$events[$ii]/\$$&/g;
	}
	print $statements{$k};
    }
    print "} \n \n" ;
    print "// Failure condition \n $state == -2 \n\n ";
    print "// Success condition \n $state == -1 \n\n "; 

}


